package org.zhaolei.service;

import cn.hutool.core.util.IdUtil;
import com.wf.captcha.ArithmeticCaptcha;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zhaolei.entity.ResponsePageEntity;
import org.zhaolei.entity.UserConditionEntity;
import org.zhaolei.entity.UserEntity;
import org.zhaolei.entity.UserRoleEntity;
import org.zhaolei.entity.auth.AuthUserEntity;
import org.zhaolei.entity.auth.CaptchaEntity;
import org.zhaolei.entity.auth.JwtUserEntity;
import org.zhaolei.entity.auth.TokenEntity;
import org.zhaolei.exception.BusinessException;
import org.zhaolei.helper.TokenHelper;
import org.zhaolei.mapper.UserMapper;
import org.zhaolei.mapper.UserRoleMapper;
import org.zhaolei.util.AssertUtil;
import org.zhaolei.util.PasswordUtil;
import org.zhaolei.util.RedisUtil;
import org.zhaolei.util.TokenUtil;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserService {

    //这个service类直接在里面写逻辑了，原来是在service类里定义接口，然后去serviceImpl文件里写逻辑

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private AuthenticationManagerBuilder authenticationManagerBuilder;

    @Autowired
    private TokenHelper tokenHelper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private PasswordUtil passwordUtil;

    @Autowired
    private UserDetailsService userDetailsService;

    private static final String CAPTCHA_PREFIX = "captcha:";

    /**
     * 通过id查询用户信息
     *
     * @param id 系统ID
     * @return 用户信息
     */
    public UserEntity findById(Long id) {
        return userMapper.findById(id);
    }

    /**
     * 添加用户
     *
     * @param userEntity 用户实体
     * @return 影响行数
     */
    @Transactional(rollbackFor = Throwable.class)
    public void insert(UserEntity userEntity) {
//        return userMapper.insert(userEntity);
        //创建用户查询实体
        UserConditionEntity userConditionEntity = new UserConditionEntity();
        userConditionEntity.setUserName(userEntity.getUserName());
        AssertUtil.isTrue(CollectionUtils.isEmpty(userMapper.searchByCondition(userConditionEntity)), "用户名已存在");

        userConditionEntity = new UserConditionEntity();
        userConditionEntity.setEmail(userEntity.getEmail());
        AssertUtil.isTrue(CollectionUtils.isEmpty(userMapper.searchByCondition(userConditionEntity)), "邮箱已存在");

        userEntity.setPassword(passwordUtil.encode(userEntity.getPassword()));
        userMapper.insert(userEntity);

        List<UserRoleEntity> userRoleEntities = buildUserRoleEntityList(userEntity);
        if (CollectionUtils.isNotEmpty(userRoleEntities)) {
            userRoleMapper.batchInsert(userRoleEntities);
        }

    }

    /**
     * 修改用户
     *
     * @param userEntity 用户实体
     * @return 影响行数
     */
    public int update(UserEntity userEntity) {
        return userMapper.update(userEntity);
    }

    /**
     * 删除用户
     *
     * @param id 用户ID
     * @return 影响行数
     */
    public int deleteById(Long id) {
        return userMapper.deleteById(id);
    }

    public ResponsePageEntity<UserEntity> searchByPage(UserConditionEntity userConditionEntity) {
//        ResponsePageEntity<UserEntity> responsePageEntity = super.searchByPage(userConditionEntity);
//        List<UserEntity> data = responsePageEntity.getData();
//        if (CollectionUtils.isNotEmpty(data)) {
//            initDept(responsePageEntity.getData());
//            initRole(responsePageEntity.getData());
//            initJob(responsePageEntity.getData());
//        }
//        return responsePageEntity;
        return null;
    }

    public TokenEntity login(AuthUserEntity authUserEntity) {

        String code = redisUtil.get(getCaptchaKey(authUserEntity.getUuid()));
        AssertUtil.hasLength(code, "验证码已过期或者不存在");
        //这一步报错后直接抛出异常，被catch的逻辑捕获了，所以没有提示验证码错误
        AssertUtil.isTrue(code.trim().equals(authUserEntity.getCode().trim()), "验证码错误");
        redisUtil.del(getCaptchaKey(authUserEntity.getUuid()));

        try {
            String decodePassword = passwordUtil.decodeRsaPassword(authUserEntity);
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(authUserEntity.getUsername(), decodePassword);

            Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            // 直接使用认证成功的用户名创建JwtUserEntity
//            List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority("User"));
//            JwtUserEntity jwtUserEntity = new JwtUserEntity(
//                    1L,
//                    authUserEntity.getUsername(),
//                    null,
//                    authorities,
//                    Arrays.asList("User")
//            );
//            String token = tokenHelper.generateToken(jwtUserEntity);
            String token = tokenHelper.generateToken((JwtUserEntity)(authentication.getPrincipal()));


            return new TokenEntity(authUserEntity.getUsername(), token, Lists.newArrayList(), 100000);
        } catch (Exception e) {
            log.info("登录失败：", e);
            throw new BusinessException(HttpStatus.FORBIDDEN.value(), "用户名或密码错误");
        }
    }


    public void logout(HttpServletRequest request) {
        String token = TokenUtil.getTokenForAuthorization(request);
        AssertUtil.hasLength(token, "Authorization token 不正确");
        tokenHelper.delToken(token);
    }

    public CaptchaEntity getCode() {
        ArithmeticCaptcha captcha = new ArithmeticCaptcha(111, 36);

        captcha.setLen(2);
        String result = "";

        try {
            result = new Double(Double.parseDouble(captcha.text())).intValue() + "";
        } catch (Exception e) {
            result = captcha.text();
        }

        String uuid = "C" + IdUtil.simpleUUID();
        //保存验证码到redis中,30秒有效期
        redisUtil.set(getCaptchaKey(uuid), result, 30);
        return new CaptchaEntity(uuid, captcha.toBase64());
    }

    private String getCaptchaKey(String uuid) {
        return String.format("%s%s", CAPTCHA_PREFIX, uuid);
    }

    public JwtUserEntity getUserInfo() {
        String currentUsername = tokenHelper.getCurrentUsername();
        return (JwtUserEntity) userDetailsService.loadUserByUsername(currentUsername);
    }
}
